# -*- coding: utf-8 -*-
import re, hashlib, sys, os, mechanize, zlib, traceback
import cStringIO as StringIO
from htmlentitydefs import name2codepoint
from urllib import urlretrieve
from lxml import etree

'''
function chuyen tu chu co dau sang chu khong dau
'''
def kdStr(str):
    if str == '': return ''
    listPattern = ["á|à|ả|ạ|ã|â|ấ|ầ|ẩ|ậ|ẫ|ă|ắ|ằ|ẳ|ặ|ẵ", 
                   "Á|À|Ả|Ạ|Ã|Â|Ấ|Ầ|Ẩ|Ậ|Ẫ|Ă|Ắ|Ằ|Ẳ|Ặ|Ẵ",
                   "đ", "Đ", "í|ì|ỉ|ị|ĩ", "Í|Ì|Ỉ|Ị|Ĩ", 
                   "é|è|ẻ|ẹ|ẽ|ê|ế|ề|ể|ệ|ễ", "É|È|Ẻ|Ẹ|Ẽ|Ê|Ế|Ề|Ể|Ệ|Ễ",
                   "ó|ò|ỏ|ọ|õ|ô|ố|ồ|ổ|ộ|ỗ|ơ|ớ|ờ|ở|ợ|ỡ", 
                   "Ó|Ò|Ỏ|Ọ|Õ|Ô|Ố|Ồ|Ổ|Ộ|Ỗ|Ơ|Ớ|Ờ|Ở|Ợ|Ỡ",
                   "ú|ù|ủ|ụ|ũ|ư|ứ|ừ|ử|ự|ữ", "Ú|Ù|Ủ|Ụ|Ũ|Ư|Ứ|Ừ|Ử|Ự|Ữ", 
                   "ý|ỳ|ỷ|ỵ|ỹ", "Ý|Ỳ|Ỷ|Ỵ|Ỹ"]
    rep = ['a', 'A', 'd', 'D', 'i', 'I', 'e', 'E', 'o', 'O', 'u', 'U', 'y', 'Y']
    if type(str).__name__ == 'unicode': str = str.encode('utf-8')
    for idx in range(len(listPattern)):
        str = re.sub(listPattern[idx], rep[idx], str)
    return str

def buildTree(url, **args):
    http, response = None, None
    tree = ''
    try:
        http = mechanize.build_opener()
        response = http.open(url)
        html = response.read()
        if args.get('outputHTML'): print(html)
        if args.get('type') == 'xml':
            parser = etree.XMLParser(encoding='utf-8')
        else:
            parser = etree.HTMLParser(encoding='utf-8')
        tree = etree.parse(StringIO.StringIO(html), parser)
    except:
        print(sys.exc_info())
    finally:
        if http is not None: del http
        if response is not None: response.close(); del response
    return tree

def extractWithRegEx(pat, matchStr, matchIdx):
    ''' Hàm chạy regex và trả kết quả ở group[matchIdx]. Nếu không có kết quả -> trả về null'''
    try:
        result = ''
        rexp = re.compile(pat)
        m = rexp.search(matchStr)
        if (m!=''):
            if matchIdx == 0: result = m.group()
            else: result = m.group(matchIdx)
        return result
    except:
        return ''

def getCRC32Unsign(textToHash=None):
    return str(zlib.crc32(textToHash) & 0xffffffffL)

def getMD5Hash(textToHash=None):
    return hashlib.md5(textToHash).hexdigest()

def getMd5Path(stringToHash):
    s = getMD5Hash(stringToHash)
    s = '{0}/{1}/{2}/{3}'.format(s[0], s[1], s[2], s[3])
    return s

def getMd5FileName(stringToHash):
    s = getMD5Hash(stringToHash)    
    s = '{0}/{1}/{2}/{3}/{4}'.format(s[0], s[1], s[2], s[3], s[4:])
    return s

def encodeUTF8(args):
    '''encode thanh utf-8 neu str la kieu unicode'''
    if type(args).__name__ == 'unicode': 
        return args.encode('utf-8')
    elif type(args).__name__ == 'list':
        data = []
        for it in args:
            if type(it).__name__ == 'unicode': 
                data.append(it.encode('utf-8'))
        return data
    elif type(args).__name__ == 'dict':
        data = {}
        for it in args:
            if type(it).__name__ == 'unicode': 
                data[it] = args[it].encode('utf-8')
        return data
    return args

def unescapeHTML(str):
    '''Chuyen tu html entities thanh ky tu binh thuong vd &nbsp; thanh dau space'''
    encodeUTF8(str)
    result = str
    try:
        result = re.sub(r'&#(\d+);', lambda m: unichr(int(m.group(1))), result)
        result = re.sub(r'&(\w+);', lambda m: unichr(name2codepoint[m.group(1)]), result)
        result = re.sub(r'&#(\d+);|&(\w+);', '', result)
    except:
        print(sys.exc_info())
    return result

def getElementText(node, tail=1, **args):
    stringify = etree.XPath("string()")
    text = ''    
    try:
        if node is not None:
            if type(node).__name__ == 'list':
                if len(node) > 0: node = node[0]
                else: return text
            if node.text is not None:
                text += node.text.strip()
            if node.tail is not None and tail==1:
                if text != '': text += ' '
                text += node.tail.strip()
            if args.get('extract_text'):
                text = re.sub(r'\s+', ' ', stringify(node).strip())
        text = encodeUTF8(text)
    except:
        exc_type, exc_value, exc_obj = sys.exc_info()
        print(traceback.print_exception(exc_type, exc_value, exc_obj))
    return text

def getAttrib(node, attrib):
    text = ''
    if node is not None and attrib != '':
        if type(node).__name__ == 'list':
            node = node[0]
        text = encodeUTF8(node.get(attrib))
    return text

def saveImage(url, path):
    ''' Lưu ảnh xuống local với tên dựa file local dựa vào hash Md5. Nếu local đã có file rồi thì 0 load nữa. '''
    saveFlag = False
    maxRetries = 3
    currentRetry = 0
    if path[-1] != '/': path += '/'
    fileName = '{0}.jpg'.format(getMd5FileName(url))
    folderName = getMd5Path(url)
    while not saveFlag and currentRetry < maxRetries:
        try:
            filePath = '{0}{1}'.format(path, fileName)
            if not os.path.isfile(filePath):
                if not os.path.exists(path + folderName):
                    os.makedirs(path + folderName)
                urlretrieve(url, filePath)
            saveFlag = True
        except:
            print '=> saveImage error: {0} >> {1} : {2}'.format(url, sys.exc_info()[0], sys.exc_info()[1])
        currentRetry += 1
    if saveFlag:
        return fileName, folderName
    return '', ''

def download(path, id, tmpLink):
    print('>>>> start download(%s, %s, %s)' % (id, path, tmpLink))
    if path[-1] != '/': path += '/'
    fn = os.path.basename(tmpLink)
    fn = fn.rsplit('.')
    ext = fn[len(fn)-1]
    if ext == '': ext = 'mp3'
    filename = '{0}.{1}'.format(getMd5FileName(id), ext)
    folderName = getMd5Path(id)
    flag = False
    maxRetries = 3
    iRetry = 0
    filesize = 0
    while not flag and iRetry < maxRetries:
        try:
            filePath = '{0}{1}'.format(path, filename)
            if not os.path.isfile(filePath):
                if not os.path.exists(path + folderName):
                    os.makedirs(path + folderName)
                location, headers = urlretrieve(tmpLink, filePath)
                downloadedsize = headers['Content-Length'] 
                filesize = os.path.getsize(filePath)
                if downloadedsize < filesize: raise Exception('file downloaded has diffirent size with source')
            flag = True
        except:
            exc_type, exc_value, exc_obj = sys.exc_info()
            print(traceback.print_exception(exc_type, exc_value, exc_obj))
        iRetry += 1
    if not flag: return '', 0
    return filename, filesize
